home *** CD-ROM | disk | FTP | other *** search
- #include <FixMath.h>
-
- #include "Tumbler_globals.h"
-
- #include "QD3D.h"
- #include "QD3DDrawContext.h"
- #include "QD3DDrawContext.h"
- #include "QD3DCamera.h"
- #include "QD3DView.h"
- #include "QD3DRenderer.h"
- #include "QD3DGroup.h"
- #include "QD3DMath.h"
-
- #include "Tumbler_prototypes.h"
-
- #include "QD3DGeometry.h"
- #include "QD3DLight.h"
-
- #include "Tumbler_camera.h"
-
- void GetGroupBBox(
- TQ3ViewObject viewObject,
- TQ3GroupObject mainGroup,
- TQ3GroupObject lightGroup,
- TQ3BoundingBox *viewBBox)
- {
- TQ3Point3D from = { 0.0, 0.0, 1.0 };
- TQ3Point3D to = { 0.0, 0.0, 0.0 };
- TQ3Vector3D up = { 0.0, 1.0, 0.0 };
-
- float fieldOfView = .52359333333;
- float hither = 0.5;
- float yon = 1.5;
-
- TQ3Status status;
-
- Q3View_StartBoundingBox(viewObject, kQ3ComputeBoundsExact);
- do {
- status = Q3DisplayGroup_Submit(mainGroup, viewObject);
- } while (Q3View_EndBoundingBox(viewObject, viewBBox) == kQ3ViewStatusRetraverse);
-
- //
- // If we have a point model, then the "viewBBox" would end up
- // being a "singularity" at the location of the point. As
- // this bounding "box" is used in setting up the camera spec,
- // we get bogus input into Escher.
-
- {
- float xSize, ySize, zSize;
-
- xSize = viewBBox->max.x - viewBBox->min.x;
- ySize = viewBBox->max.y - viewBBox->min.y;
- zSize = viewBBox->max.z - viewBBox->min.z;
-
- if (xSize <= kQ3RealZero &&
- ySize <= kQ3RealZero &&
- zSize <= kQ3RealZero) {
-
- viewBBox->max.x += 0.0001;
- viewBBox->max.y += 0.0001;
- viewBBox->max.z += 0.0001;
-
- viewBBox->min.x -= 0.0001;
- viewBBox->min.y -= 0.0001;
- viewBBox->min.z -= 0.0001;
- }
- }
- }
-
- #define SIZESCALE 0.03
- #define POSSCALE 0.5
- void AdjustLightsPositions(
- DocumentPtr theDocument)
- {
- #if defined(ESCHER_VER_15) && ESCHER_VER_15
-
- TQ3BoundingBox viewBBox;
- TQ3Vector3D diagonalVector, radius;
- TQ3GroupPosition position, lightPosition;
- TQ3Object ellipsoid;
- TQ3Point3D origin;
- float maxDimension;
- TQ3GroupObject lightGroup;
- TQ3LightObject theLight;
- float ratio;
-
- GetGroupBBox(theDocument->theView, theDocument->documentGroup, nil, &viewBBox);
-
- Q3Point3D_Subtract(&viewBBox.max,
- &viewBBox.min,
- &diagonalVector);
- maxDimension = Q3Vector3D_Length(&diagonalVector);
- maxDimension *= 8.0 / 7.0;
-
- ratio = 6.0 / maxDimension;
-
- /* Adjust the light from the viewer first */
-
- Q3View_GetLightGroup(theDocument->theView, &lightGroup);
-
- Q3Group_GetFirstPosition(lightGroup, &lightPosition);
-
- Q3Group_GetPositionObject(lightGroup, lightPosition, &theLight);
-
- origin.x = -10.0;
- origin.y = 10.0;
- origin.z = 30.0;
-
- Q3PointLight_SetLocation(theLight, &origin);
- Q3Object_Dispose(theLight);
-
- /* Set the geometry and the light parameters for the red light */
- Q3Group_GetFirstPositionOfType(theDocument->light1,
- kQ3ShapeTypeGeometry, &position);
-
- Q3Group_GetPositionObject(theDocument->light1, position, &ellipsoid);
-
- origin.x = ratio * diagonalVector.x * POSSCALE;
- origin.y = ratio * diagonalVector.y * POSSCALE;
- origin.z = ratio * diagonalVector.z * POSSCALE;
- Q3Ellipsoid_SetOrigin( ellipsoid, &origin);
-
- radius.x = radius.z = 0.0;
- radius.y = ratio * maxDimension * SIZESCALE;
- Q3Ellipsoid_SetOrientation( ellipsoid, &radius);
-
- radius.x = radius.y = 0.0;
- radius.z = ratio * maxDimension * SIZESCALE;
- Q3Ellipsoid_SetMajorRadius( ellipsoid, &radius);
-
- radius.z = radius.y = 0.0;
- radius.x = ratio * maxDimension * SIZESCALE;
- Q3Ellipsoid_SetMinorRadius( ellipsoid, &radius);
-
- Q3Group_GetNextPosition(lightGroup, &lightPosition);
- Q3Group_GetPositionObject(lightGroup, lightPosition, &theLight);
- Q3PointLight_SetLocation(theLight, &origin);
-
- Q3Object_Dispose(theLight);
-
- Q3Object_Dispose(ellipsoid);
-
-
- /* Set the geometry and the light parameters for the green light */
- Q3Group_GetFirstPositionOfType(theDocument->light2,
- kQ3ShapeTypeGeometry, &position);
-
- Q3Group_GetPositionObject(theDocument->light2, position, &ellipsoid);
-
- origin.x = - ratio * diagonalVector.x * POSSCALE;
- origin.y = - ratio * diagonalVector.y * POSSCALE;
- origin.z = ratio * diagonalVector.z * POSSCALE;
- Q3Ellipsoid_SetOrigin( ellipsoid, &origin);
-
- radius.x = radius.z = 0.0;
- radius.y = ratio * maxDimension * SIZESCALE;
- Q3Ellipsoid_SetOrientation( ellipsoid, &radius);
-
- radius.x = radius.y = 0.0;
- radius.z = ratio * maxDimension * SIZESCALE;
- Q3Ellipsoid_SetMajorRadius( ellipsoid, &radius);
-
- radius.z = radius.y = 0.0;
- radius.x = ratio * maxDimension * SIZESCALE;
- Q3Ellipsoid_SetMinorRadius( ellipsoid, &radius);
-
- Q3Group_GetNextPosition(lightGroup, &lightPosition);
- Q3Group_GetPositionObject(lightGroup, lightPosition, &theLight);
- Q3PointLight_SetLocation(theLight, &origin);
-
- Q3Object_Dispose(theLight);
- Q3Object_Dispose(ellipsoid);
-
- /* Set the geometry and the light parameters for the blue light */
- Q3Group_GetFirstPositionOfType(theDocument->light3,
- kQ3ShapeTypeGeometry, &position);
-
- Q3Group_GetPositionObject(theDocument->light3, position, &ellipsoid);
-
- origin.x = 0.0;
- origin.y = ratio * diagonalVector.y * POSSCALE + 1.0;
- origin.z = 0.0;
- Q3Ellipsoid_SetOrigin( ellipsoid, &origin);
-
- radius.x = radius.z = 0.0;
- radius.y = ratio * maxDimension * SIZESCALE;
- Q3Ellipsoid_SetOrientation( ellipsoid, &radius);
-
- radius.x = radius.y = 0.0;
- radius.z = ratio * maxDimension * SIZESCALE;
- Q3Ellipsoid_SetMajorRadius( ellipsoid, &radius);
-
- radius.z = radius.y = 0.0;
- radius.x = ratio * maxDimension * SIZESCALE;
- Q3Ellipsoid_SetMinorRadius( ellipsoid, &radius);
-
- Q3Group_GetNextPosition(lightGroup, &lightPosition);
- Q3Group_GetPositionObject(lightGroup, lightPosition, &theLight);
- Q3PointLight_SetLocation(theLight, &origin);
-
- Q3Object_Dispose(theLight);
- Q3Object_Dispose(ellipsoid);
-
- Q3Object_Dispose(lightGroup);
- #endif
- }
-
-
-
- //===========================================================================
- //
- // Routine: AdjustCamera()
- //
- // Comments:
- //
- //===========================================================================
-
- TQ3Point3D AdjustCamera(
- DocumentPtr theDocument,
- short winWidth,
- short winHeight)
- {
- float fieldOfView;
- float hither;
- float yon;
- TQ3CameraPlacement placement;
- TQ3CameraRange range;
- TQ3BoundingBox viewBBox;
- long fromAxis;
- float maxDimension;
- float xSize, ySize, zSize;
- float weights[2] = { 0.5, 0.5 };
- TQ3Point3D points[2];
- TQ3Vector3D viewVector;
- TQ3Vector3D normViewVector;
- TQ3Vector3D eyeToFrontClip;
- TQ3Vector3D eyeToBackClip;
- float viewDistance;
- TQ3Vector3D diagonalVector;
- float ratio;
- TQ3CameraObject camera;
-
- Q3View_GetCamera(theDocument->theView, &camera);
-
- GetGroupBBox(theDocument->theView, theDocument->documentGroup,
- theDocument->dynamicLights, &viewBBox);
-
- /*
- * If we have a point model, then the "viewBBox" would end up
- * being a "singularity" at the location of the point. As
- * this bounding "box" is used in setting up the camera spec,
- * we get bogus input into Escher.
- *
- * Therefore, determine if the bounding box is really really small
- * (kQ3RealZero) and increase it so it's just a little small.
- */
- xSize = viewBBox.max.x - viewBBox.min.x;
- ySize = viewBBox.max.y - viewBBox.min.y;
- zSize = viewBBox.max.z - viewBBox.min.z;
-
- if (xSize <= kQ3RealZero &&
- ySize <= kQ3RealZero &&
- zSize <= kQ3RealZero)
- {
- viewBBox.max.x += 0.0001;
- viewBBox.max.y += 0.0001;
- viewBBox.max.z += 0.0001;
-
- viewBBox.min.x -= 0.0001;
- viewBBox.min.y -= 0.0001;
- viewBBox.min.z -= 0.0001;
- }
-
- points[0] = viewBBox.min;
- points[1] = viewBBox.max;
-
- /*
- This sets the "documentGroupCenter" to the center of our bbox.
-
- (point[0] * weight[0] + point[1] * weight[1]) or
-
- (point[0] * 0.5 + point[1] * 0.5) or
-
- point[0] + point[1]
- -------------------, essentially, the average of the points.
- 2
- */
- Q3Point3D_AffineComb(points, weights, 2, &theDocument->documentGroupCenter);
-
- /*
- * The "from" point is on a vector perpendicular to the plane
- * in which the bounding box has greatest dimension. As "up" is
- * always in the positive y direction, look at x and z directions.
- */
- xSize = viewBBox.max.x - viewBBox.min.x;
- zSize = viewBBox.max.z - viewBBox.min.z;
-
- if (xSize > zSize) {
- fromAxis = kQ3AxisZ;
- } else {
- fromAxis = kQ3AxisX;
- }
-
- /*
- * Compute the length of the diagonal of the bounding box.
- *
- * The hither and yon planes are adjusted so that the
- * diagonal of the bounding box is 7/8 the size of the
- * minimum dimension of the view frustum. The diagonal is used instead
- * of the maximum size (in x, y, or z) so that when you rotate
- * the object, the corners don't get clipped out.
- */
- Q3Point3D_Subtract(
- &viewBBox.max,
- &viewBBox.min,
- &diagonalVector);
-
- maxDimension = Q3Vector3D_Length(&diagonalVector);
- maxDimension *= 8.0 / 7.0;
-
- /*
- This scales all objects in the scene so they gets scaled to fit
- in the window. We're using the length of the diagonal of the box
- to scale. We can now assume the maximum dimension of the model is
- 1.0.
- */
- ratio = 1.0 / maxDimension;
-
- theDocument->documentGroupScale = ratio;
-
- /*
- Now, adjust the camera's hither and yon planes.
-
- (We don't edit the camera location, etc. as it will always be in
- the same location - we always scale the objects and leave the camera
- in the same location.)
- */
- Q3Camera_GetPlacement(camera, &placement);
-
- /*
- Compute the camera vector
- */
- Q3Point3D_Subtract(
- &placement.cameraLocation,
- &placement.pointOfInterest,
- &viewVector);
-
- viewDistance = Q3Vector3D_Length(&viewVector);
- Q3Vector3D_Normalize(&viewVector, &normViewVector);
-
- /*
- Essentially, here we are "scaling" the normalized camera vector
- to a location in front of the object (half of maxDimension)
- and another location in back of the camera.
-
- Assume these three vectors below are co-linear.
-
- A = ratio * maxDimension/2.0
-
- |------hither-------||----A----|----A-----|
- |------------------yon--------------------|
-
- camera location
- * -----------------> * eyeToFrontClip
- * --------camera vector------> * object center
- * --------------------------------------> * eyeToBackClip
- */
-
- Q3Vector3D_Scale(&normViewVector,
- viewDistance - ratio * maxDimension/2.0,
- &eyeToFrontClip);
-
- Q3Vector3D_Scale(&normViewVector,
- viewDistance + ratio * maxDimension/2.0,
- &eyeToBackClip);
-
- hither = Q3Vector3D_Length(&eyeToFrontClip);
- yon = Q3Vector3D_Length(&eyeToBackClip);
-
- /*
- Set the field of view. This will determine the width of our lens.
- Or, (more appropriately), as someone here mentioned,
- where the blinders begin in our image.
-
- This is the angle created by the triangle of the camera vector and the
- maximum dimension of our object.
-
- We use the hither point because it's closest and convenient.
-
- we know:
-
- atan(opposite/adjacent) = the angle we need
-
- Our angle is at the camera, so our "opposite" leg is "A" (above)
- our "adjacent" leg is the hither length.
-
- We double our result because our triangle gets us the half angle
- for the entire field of view.
- */
-
- fieldOfView = 2 * atan((ratio * maxDimension/2.0)/hither);
-
- range.hither = hither;
- range.yon = yon;
-
- Q3Camera_SetRange(camera, &range);
-
- Q3ViewAngleAspectCamera_SetFOV(
- camera, fieldOfView);
-
- /*
- And finally, set up our aspect ratio depending on how big the
- window is.
- */
- Q3ViewAngleAspectCamera_SetAspectRatio(
- camera, (float) winWidth / (float) winHeight);
-
- Q3Object_Dispose(camera);
-
- return(theDocument->documentGroupCenter);
- }
-
-